﻿using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using UnityEngine.SceneManagement;
using SgLib;

public enum GameState
{
    Prepare,
    Playing,
    Paused,
    PreGameOver,
    GameOver
}

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    public static bool isRestart = false;

    public static event System.Action<GameState, GameState> GameStateChanged = delegate { };

    public GameState GameState
    {
        get
        {
            return _gameState;
        }
        private set
        {
            if (value != _gameState)
            {
                GameState oldState = _gameState;
                _gameState = value;

                GameStateChanged(_gameState, oldState);
            }
        }
    }

    private GameState _gameState = GameState.Prepare;

    public static int GameCount
    { 
        get { return _gameCount; } 
        private set { _gameCount = value; } 
    }

    private static int _gameCount = 0;

    [Header("Set the target frame rate for this game")]
    [Tooltip("Use 60 for games requiring smooth quick motion, set -1 to use platform default frame rate")]
    public int targetFrameRate = 30;

    // List of public variable for gameplay tweaking
    [Header("Gameplay Config")]

    [Range(0f, 1f)]
    public float coinFrequency = 0.1f;

    // List of public variables referencing other objects
    [Header("Object References")]
    public GameObject platformer;
    public GameObject player;
    public MouseOverDetector characterSelectBtnMOD;

    [Header("Parallaxing")]
    public Transform[] backgrounds;
    public float[] parallaxScales;
    public float smoothing;
    private Transform cam;
    private Vector3 previousCamPos;

    void OnEnable()
    {
        PlayerController.PlayerStarted += PlayerController_PlayerStarted;
        PlayerController.PlayerDied += PlayerController_PlayerDied;
    }



    void OnDisable()
    {
        PlayerController.PlayerDied -= PlayerController_PlayerDied;
    }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            DestroyImmediate(Instance.gameObject);
            Instance = this;
        }
        cam = Camera.main.transform;
        int current = CharacterManager.Instance.CurrentCharacterIndex;
        player = Instantiate(CharacterManager.Instance.characters[current], Vector3.zero, Quaternion.identity);
    }

    void OnDestroy()
    {
        if (Instance == this)
        {
            Instance = null;
        }
    }

    // Use this for initialization
    void Start()
    {
        // Initial setup
        Application.targetFrameRate = targetFrameRate;
        ScoreManager.Instance.Reset();

        previousCamPos = cam.position;
        parallaxScales = new float[backgrounds.Length];
        for (int i = 0; i < backgrounds.Length; i++)
        {
            parallaxScales[i] = backgrounds[i].position.z * -1;
        }

        PrepareGame();

        if (isRestart)
        {
            isRestart = false;
            StartGame();
        }

    }

    void PlayerController_PlayerStarted()
    {
        if (SoundManager.Instance.background != null)
        {
            SoundManager.Instance.PlayMusic(SoundManager.Instance.background);
        }
    }

    // Listens to the event when player dies and call GameOver
    void PlayerController_PlayerDied()
    {
        GameOver();
    }

    // Make initial setup and preparations before the game can be played
    public void PrepareGame()
    {
        platformer.SetActive(true);
        player.SetActive(false);
        GameState = GameState.Prepare;
    }

    // A new game official starts
    public void StartGame()
    {
        platformer.SetActive(true);
        player.SetActive(true);

        GameState = GameState.Playing;

    }

    // Called when the player died
    public void GameOver()
    {
        Invoke("StopBackgroundMusic", 1f);
        SoundManager.Instance.PlaySound(SoundManager.Instance.gameOver);
        GameState = GameState.GameOver;
        GameCount++;
    }

    void StopBackgroundMusic()
    {
        if (SoundManager.Instance.background != null)
        {
            SoundManager.Instance.StopMusic();
        }
    }

    // Start a new game
    public void RestartGame(float delay = 0)
    {
        StartCoroutine(CRRestartGame(delay));
    }

    IEnumerator CRRestartGame(float delay = 0)
    {
        yield return new WaitForSeconds(delay);
        isRestart = true;
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < backgrounds.Length; i++)
        {
            float parallax = (previousCamPos.x - cam.position.x) * parallaxScales[i];

            float backGrTargetPosX = backgrounds[i].position.x + parallax;
            Vector3 backGrTargetPos = new Vector3(backGrTargetPosX, backgrounds[i].position.y, backgrounds[i].position.z);

            backgrounds[i].position = Vector3.Lerp(backgrounds[i].position, backGrTargetPos, smoothing * Time.deltaTime);
        }
        if (player.transform.position.y<-20) 
        {
            GameOver();
            player.transform.SetPositionAndRotation(new Vector3(0, -21, 0), Quaternion.Euler(0, 0, 0));
        }

        previousCamPos = cam.position;
    }

        
}
